package zcatt.ex008.ui.navigator;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.ui.progress.UIJob;

//提取text文件中的"^Chapter/sXXX"

public class MyContentProvider implements ITreeContentProvider, IResourceChangeListener, IResourceDeltaVisitor {


	static final String EXTENSION = "text";
	static final Object[] NO_CHILDREN = new Object[0];
	final Map<IFile, ChapterTreeData[]> cachedModelMap = new HashMap<>();
	StructuredViewer viewer;
	
	public MyContentProvider() {
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
	}

	@Override
	public void dispose() {
		cachedModelMap.clear();
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
	}
	
	@Override
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		if (oldInput != null && !oldInput.equals(newInput))
			cachedModelMap.clear();
		this.viewer = (StructuredViewer) viewer;
	}

	@Override		//override IResourceChangeListener
	public void resourceChanged(IResourceChangeEvent event) {
		IResourceDelta delta = event.getDelta();
		try {
			delta.accept(this);
		} catch (CoreException e) {
			e.printStackTrace();
		}
	}
	
	@Override		//override IResourceDeltaVisitor
	public boolean visit(IResourceDelta delta) throws CoreException {
		IResource source = delta.getResource();
		switch (source.getType()) {
		case IResource.ROOT:
		case IResource.PROJECT:
		case IResource.FOLDER:
			return true;
		case IResource.FILE:
			final IFile file = (IFile) source;
			if (EXTENSION.equals(file.getFileExtension())) {
				updateModel(file);
				new UIJob("Update Model in CommonViewer") {
					@Override
					public IStatus runInUIThread(IProgressMonitor monitor) {
						if (viewer != null && !viewer.getControl().isDisposed())
							viewer.refresh(file);
						return Status.OK_STATUS;
					}
				}.schedule();
			}
			return false;
		}
		return false;
	}

	@Override
	public Object[] getElements(Object inputElement) {
		return getChildren(inputElement);
	}

	@Override
	public boolean hasChildren(Object element) {
		if(element instanceof ChapterTreeData)
			return false;
		if(element instanceof IFile && EXTENSION.equals(((IFile)element).getFileExtension()))
			return true;

		return false;
	}
	
	@Override
	public Object[] getChildren(Object parentElement) {
		Object[] children = NO_CHILDREN;
		
		if(parentElement instanceof ChapterTreeData)
		{
			//children = NO_CHILDREN;
		}
		else if (parentElement instanceof IFile)
		{
			IFile modelFile = (IFile) parentElement;
			if(EXTENSION.equals(modelFile.getFileExtension()))
			{
				children = cachedModelMap.get(modelFile);
				if(children == null && updateModel(modelFile))
				{
					children = cachedModelMap.get(modelFile);					
				}
			}		
		}
		return children;
	}

	@Override
	public Object getParent(Object element) {
		if(element instanceof ChapterTreeData)
		{
			ChapterTreeData data = (ChapterTreeData) element;
			return data.getFile();
		}

		return null;
	}


	//return true if update effectively	
	synchronized boolean updateModel(IFile modelFile) {	//注意使用 synchronized
		if(EXTENSION.equals(modelFile.getFileExtension())
				&& modelFile.exists())
		{
			//从file中提取ChapterTreeData
			
			List<ChapterTreeData> list = new ArrayList<>();
			Pattern pattern = Pattern.compile("^Chapter\\s\\w+", Pattern.CASE_INSENSITIVE);
			
			try {
				BufferedReader reader = new BufferedReader(new InputStreamReader(modelFile.getContents()));
				String line;
				while((line = reader.readLine())!= null)
				{
					Matcher m = pattern.matcher(line);
					if(m.find())
					{
						ChapterTreeData data = new ChapterTreeData(m.group(0), modelFile);
						list.add(data);						
						System.out.println("chapterTreeData= "+data);
					}					
				}
				ChapterTreeData[] array = list.toArray(new ChapterTreeData[list.size()]);
				cachedModelMap.put(modelFile, array);
				return true;
			}
			catch(Exception e)
			{
				cachedModelMap.remove(modelFile);
				
			}
		}
		
		return false;
	}
}
